package com.apes.fn.scm.income;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apes.fn.scm.internal.help.repository.InternalHelpReturnApprovalRepository;
import com.apes.fn.scm.retailOrder.model.RetailOrder;
import com.apes.fn.scm.retailOrder.repository.RetailOrderRepository;
import com.apes.fn.server.servicePlan.model.ServicePlan;
import com.apes.fn.server.servicePlan.model.ServicePlanItem;
import com.apes.fn.server.servicePlan.repository.ServicePlanItemRepository;
import com.apes.fn.server.servicePlan.repository.ServicePlanRepository;
import com.apes.fn.server.servicePlan.service.ConditionBuilder;
import com.apes.fn.server.workOrder.model.MaintenanceOrder;
import com.apes.fn.server.workOrder.repository.MaintenanceOrderRepository;
import com.apes.framework.api.DomainService;
import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.logger.ApesLoggerService;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.plugin.outbox.OutboxEventService;
import com.apes.framework.plugin.outbox.OutboxPayloadWrapper;
import com.apes.framework.plugin.outbox.annotation.OutboxSubscriber;
import com.apes.framework.util.LogicalUtil;
import com.apes.framework.util.MapUtil;
import com.apes.scm.account.tax.repository.TaxRepository;
import com.apes.scm.contract.model.Contract;
import com.apes.scm.income.model.Income;
import com.apes.scm.income.model.IncomeItem;
import com.apes.scm.income.repository.IncomeRepository;
import com.apes.scm.invoice.model.Invoice;
import com.apes.scm.invoice.repository.InvoiceltemDao;
import com.apes.scm.masterdata.enumeration.model.Enumeration;
import com.apes.scm.masterdata.enumeration.repository.EnumerationRepository;
import com.apes.scm.masterdata.finance.model.IncomeType;
import com.apes.scm.masterdata.finance.repository.IncomeTypeRepository;
import com.apes.scm.masterdata.frame.model.Dept;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.masterdata.party.repository.PartyRoleRepository;
import com.apes.scm.sal.saleOrder.SaleOrder;
import com.apes.scm.sal.saleOrder.SaleOrderRepository;
import com.apes.scm.voucher.model.Voucher;
import com.apes.scm.voucher.repository.VoucherRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @program: apes-server
 * @description: 业务单据创建收入单
 * @author: czs
 * @create: 2022-10-18 11:53
 **/
@Service("bizOrderCreatIncomeService")
public class BizOrderCreatIncomeService extends DomainService {

    @Autowired
    private EnumerationRepository enumerationRepository;
    @Autowired
    private ServicePlanRepository servicePlanRepository;
    @Autowired
    private ApesLoggerService apesLoggerService;
    @Autowired
    private MaintenanceOrderRepository maintenanceOrderRepository;
    @Autowired
    private SaleOrderRepository saleOrderRepository;
    @Autowired
    private InvoiceltemDao invoiceltemDao;

    /**
     * 测试
     *
     * @param request
     * @return
     */
    public void test(SimpleRequest request) {
        Voucher invoice = SpringManager.getBean(VoucherRepository.class).getOne(request.get("id").toString());
        supplierPurchaseCreateIncome(invoice);
    }

    @OutboxSubscriber(name = "(经销)凭证生成收入单", condition = "voucherType=='SUPPLIER_PURCHASE' and inventoryMode == 'IM_OWN'")
    private void supplierPurchaseCreateIncome(Voucher voucher) {
        JSONArray jsonArray = invoiceltemDao.findServicePlan(voucher.getOrigin());
        if (jsonArray.size() > 0 && "师人订制".equals(((JSONObject) jsonArray.get(0)).get("CHANNEL_NAME"))) {
            //卡内
            knCreateSupplierIncome(voucher, "distribution");
        } else {
            //富登
            fdCreateSupplierIncome(voucher, "distribution");
        }
        //集群空间
        jekunAutoSpaceCreateOrder(voucher, this::findSourceServicePlan);
    }


    @OutboxSubscriber(name = "(代销)凭证生成收入单", condition = "voucherType=='SUPPLIER_CONSUME'")
    private void supplierConsumeCreateIncome(Voucher voucher) {
        JSONArray jsonArray = invoiceltemDao.findServicePlan(voucher.getOrigin());
        if (jsonArray.size() > 0 && "师人订制".equals(((JSONObject) jsonArray.get(0)).get("CHANNEL_NAME"))) {
            //卡内
            knCreateSupplierIncome(voucher, "distribution");
        } else {
            //富登
            fdCreateSupplierIncome(voucher, "distribution");
        }
        //集群空间
        jekunAutoSpaceCreateOrder(voucher, this::findSourceServicePlan);
    }

    @OutboxSubscriber(name = "凭证生成收入单(寄售-采购凭证)", condition = "voucherType=='SUPPLIER_PURCHASE' and inventoryMode == 'IM_CONSIGN'")
    private void supplierConsignPurchaseCreateIncome(Voucher voucher) {
        //集群空间
        jekunAutoSpaceCreateOrder(voucher, this::findSourceServicePlan);
    }

    private void testFD(SimpleRequest request) {
        JSONObject jo = request.getJO();
        String id = jo.getString("id");
        Voucher one = SpringManager.getBean(VoucherRepository.class).findOne(id);
        Voucher voucher = SpringManager.getBean(VoucherRepository.class).saveAndFlush(one);
        int i = 1 / 0;
    }

    private void testJEKUNAUTO(JSONObject jo) {
        List<String> list = Arrays.asList("000817", "006801");
        Date startDate = jo.getDate("startDate");
        List<Voucher> voucherList = SpringManager.getBean(VoucherRepository.class).findAll(JpaDsl.toCriteria("voucherType", "EQ", "SUPPLIER_CONSUME", "partner.id", "IN", list, "createDate", "GTE", startDate));
        List<Voucher> voucherList2 = SpringManager.getBean(VoucherRepository.class).findAll(JpaDsl.toCriteria("voucherType", "EQ", "SUPPLIER_PURCHASE", "inventoryMode", "EQ", "IM_OWN", "partner.id", "IN", list, "createDate", "GTE", startDate));
        voucherList.addAll(voucherList2);
        List<String> collect = voucherList.stream().map(Voucher::getId).collect(Collectors.toList());
        List<Income> incomeList = SpringManager.getBean(IncomeRepository.class).findAll(JpaDsl.toCriteria("source", "IN", collect));
        List<String> collect1 = incomeList.stream().map(Income::getSource).collect(Collectors.toList());
        for (String s : collect1) {
            collect.remove(s);
        }
        System.out.println(collect);
        for (String s : collect) {
            jekunAutoSpaceCreateOrder(SpringManager.getBean(VoucherRepository.class).findOne(s), this::findSourceServicePlan);
        }
    }

    /**
     * 富登脚垫外协生成供应商收入单
     *
     * @param voucher
     */
    private void fdCreateSupplierIncome(Voucher voucher, String cooperationType) {
        Contract contract = voucher.getContract();
        if (contract == null) return;
        String id = contract.getCooperation().getId();
        if (!id.equals(cooperationType)) return;
        ServicePlan servicePlan = checkFD(voucher, cooperationType);
        if (servicePlan == null) return;
        Dept dept = servicePlan.getBelongDept();
        Enumeration operation = dept.getCompany().getParty().getCorporate().getOperation();
        Income income = new Income();
        if ("001073".equals(operation.getId())) {
            // 赋能店的公司 为1007
            income.setCompany(SpringManager.getBean(PartyRoleRepository.class).findOne("1007"));
        } else {
            // 非赋能店的公司取值为 1001
            income.setCompany(SpringManager.getBean(PartyRoleRepository.class).findOne("1001"));
        }
        income.setThirdId(servicePlan.getSupplierRef());
        income.setPartner(voucher.getContract().getPartner());  // 供应商取值：获取业务凭证的合同中的合作伙伴
        income.setContract(voucher.getContract());
        income.setCooperation(voucher.checkCooperation());
        income.setInComeCategory(enumerationRepository.findById("cost").get());
        income.setSourceBusinessType(voucher.getInnerBusinessType());
        income.setOrigin(servicePlan.getId());
        income.setFnCustomerExpand(servicePlan.getFnCustomerExpand().getId());
        income.setCarLicense(servicePlan.getFnCustomerExpand().getCarLicense());
        income.setSource(voucher.getId());
        income.setNote("富登脚垫自动创建费用单车牌:" + servicePlan.getFnCustomerExpand().getCarLicense());

        //促销费
        List<MaintenanceOrder> maintenanceOrders = maintenanceOrderRepository.findAll(JpaDsl.toCriteria(
                "servicePlanItem", "in", servicePlan.getServicePlanItems(),
                "businessType", "EQ", "out"
        ));
        IncomeType incomeType = SpringManager.getBean(IncomeTypeRepository.class).findOne("A08");
        maintenanceOrders.forEach(maintenanceOrder -> {
            IncomeItem incomeItem = new IncomeItem();
            incomeItem.setIncomeType(incomeType);
            income.setAmount(income.getAmount() + maintenanceOrder.getCommissionAmount());
            incomeItem.setIncomeAmount(maintenanceOrder.getCommissionAmount());
            incomeItem.setStartDate(voucher.getCreateDate());
            incomeItem.setEndDate(voucher.getCreateDate());
            incomeItem.setTax(SpringManager.getBean(TaxRepository.class).findById(4L).get());
            incomeItem.setNote(dept.getName() + " " + new SimpleDateFormat("yyyy年MM月dd日").format(new Date()));
            income.getIncomeItems().add(incomeItem);
        });
        income.setWrite(false);
        PartyRole system = SpringManager.getBean(PartyRoleRepository.class).findOne("system");
        Object invoke = this.invoke("income.supplier.createBySystem", income);
        income.setCreator(system.getId());

        writeLogger(income, "创建", "富登脚垫自动创建");
        income.setApproveUID(system);

        invoke = invoke("income.supplier.approve", invoke);
        writeLogger(income, "审核", "富登脚垫自动审核");
    }

    private void knCreateSupplierIncome(Voucher voucher, String cooperationType) {
        Contract contract = voucher.getContract();
        if (contract == null) return;
        String id = contract.getCooperation().getId();
        if (!id.equals(cooperationType)) return;
        ServicePlan servicePlan = checkFD(voucher, cooperationType);
        if (servicePlan == null) return;
        Dept dept = servicePlan.getBelongDept();
        Enumeration operation = dept.getCompany().getParty().getCorporate().getOperation();
        Income income = new Income();
        if ("001073".equals(operation.getId())) {
            // 赋能店的公司 为1007
            income.setCompany(SpringManager.getBean(PartyRoleRepository.class).findOne("1007"));
        } else {
            // 非赋能店的公司取值为 1001
            income.setCompany(SpringManager.getBean(PartyRoleRepository.class).findOne("1001"));
        }
        income.setPartner(voucher.getContract().getPartner());  // 供应商取值：获取业务凭证的合同中的合作伙伴
        income.setCooperation(voucher.checkCooperation());//合作方式编码
        income.setInComeCategory(enumerationRepository.findById("rebate").get());//收入类别
        income.setSource(voucher.getId());//来源单据
        income.setSourceBusinessType(voucher.getInnerBusinessType());//来源单据类型
        income.setOrigin(servicePlan.getId());
        income.setSourceBusinessKey(servicePlan.getInnerBusinessType());
        income.setCarLicense(servicePlan.getFnCustomerExpand().getCarLicense());
        income.setContract(voucher.getContract());
        income.setThirdId(servicePlan.getSupplierRef());//第三方单号
        income.setFnCustomerExpand(servicePlan.getFnCustomerExpand().getId());
        income.setNote("师人订制业务自动创建费用单！");
        //促销费
        List<MaintenanceOrder> maintenanceOrders = maintenanceOrderRepository.findAll(JpaDsl.toCriteria(
                "servicePlanItem", "in", servicePlan.getServicePlanItems(),
                "businessType", "EQ", "out"
        ));


        IncomeType incomeType = SpringManager.getBean(IncomeTypeRepository.class).findOne("A07");
        maintenanceOrders.forEach(maintenanceOrder -> {

            IncomeItem incomeItem = new IncomeItem();
            incomeItem.setIncomeType(incomeType);//收入类型
            List<ServicePlanItem> servicePlanItems = servicePlan.getServicePlanItems();
            servicePlanItems.forEach(v -> {
                if (v.getProduct().getId().equals(maintenanceOrder.getProduct().getId())) {
                    incomeItem.setIncomeAmount(v.getCommissionAmount());
                }
            });

            income.setAmount(income.getAmount() + incomeItem.getIncomeAmount());
            incomeItem.setStartDate(voucher.getCreateDate());
            incomeItem.setEndDate(voucher.getCreateDate());
            if ("001073".equals(operation.getId())) {
                // 赋能店的公司 为1007
                incomeItem.setTax(SpringManager.getBean(TaxRepository.class).findById(5L).get());
            } else {
                // 非赋能店的公司取值为 1001
                incomeItem.setTax(SpringManager.getBean(TaxRepository.class).findById(4L).get());
            }
            incomeItem.setNote(dept.getName() + " " + new SimpleDateFormat("yyyy年MM月dd日").format(new Date()));
            if(incomeItem.getIncomeAmount() != 0) {
                income.getIncomeItems().add(incomeItem);
            }

        });
        income.setWrite(false);
        PartyRole system = SpringManager.getBean(PartyRoleRepository.class).findOne("system");
        Object invoke = this.invoke("income.supplier.createBySystem", income);
        income.setCreator(system.getId());

        writeLogger(income, "创建", "师人订制业务自动创建");
        income.setApproveUID(system);

        invoke = invoke("income.supplier.approve", invoke);
        writeLogger(income, "审核", "师人订制业务自动审核");
    }

    private void writeLogger(Income income, String operate, String remake) {
        apesLoggerService.sendSynEvent("event:ir.logger.create",
                MapUtil.mapper(
                        "businessType", income.getInnerBusinessType(),
                        "businessKey", income.getInnerBusinessKey(),
                        "operate", operate,
                        "workPostName", null,
                        "remark", remake,
                        "operator_id", 0)
        );
    }

    private ServicePlan checkFD(Voucher voucher, String cooperationType) {
        ServicePlan servicePlan;
        //consignment经销
        if (cooperationType.equals("consignment")) {
            String businessType = voucher.getOriginBusinessType();
            String source = voucher.getOrigin();
            if (!businessType.equals("RetailOrder")) return null;
            RetailOrder retailOrder = SpringManager.getBean(RetailOrderRepository.class).findOne(source);
            if (retailOrder.getSource() == null) return null;
            servicePlan = servicePlanRepository.findOne(retailOrder.getSource());
            if (servicePlan == null) return null;
            if (servicePlan.getChannel() == null) return null;
            if (!(servicePlan.getChannel().getName().equals("富登") || servicePlan.getChannel().getName().equals("师人订制")))
                return null;
        } else {
            //consignment代销
            String businessType = voucher.getOriginBusinessType();
            if (!businessType.equals("ServicePlan")) return null;
            servicePlan = servicePlanRepository.findOne(voucher.getOrigin());
            //不取 03经销带安凭证
            if (!"03".equals(voucher.getClassification())) return null;
            if (servicePlan == null) return null;
            if (!(servicePlan.getChannel().getName().equals("富登") || servicePlan.getChannel().getName().equals("师人订制")))
                return null;
        }

        return servicePlan;
    }

    /**
     * 外协派工集群空间类型生成供应商收入单和平台费用单
     *
     * @param voucher
     */
    private void jekunAutoSpaceCreateOrder(Voucher voucher, Function<Voucher, ServicePlan> function) {
        String source = voucher.getOrigin();
        if (source == null) return;
        ServicePlan servicePlan = function.apply(voucher);
        if (servicePlan == null) return;
        if (!LogicalUtil.in(voucher.getClassification(), "04", "03")) return;

//        String id = voucher.getPartner().getId();
//        if (!id.equals("000817")&&!id.equals("006801"))return;

        //获取工单按合同分组
        List<String> idList = servicePlan.getServicePlanItems().stream()
                .map(servicePlanItem -> servicePlanItem.getInnerServicePlanItem() == null ? servicePlanItem.getId() : servicePlanItem.getInnerServicePlanItem())
                .collect(Collectors.toList());

        Map<Contract, List<MaintenanceOrder>> contractListMap = maintenanceOrderRepository.findAll(JpaDsl.toCriteria(
                "servicePlanItem.id", "in", idList,
                "businessType", "EQ", "out"
        )).stream().filter(order -> {
            ConditionBuilder cx_kjjh = new ConditionBuilder.Builder("CX_KJJH")
                    .setSupplierId(order.getSupplier())
                    .setDept(order.getBelongDept())
                    .product(order.getProduct())
                    .build()
                    .execConditionStrategy()
                    .formatAmount();
            JSONObject spacePlanPrice = cx_kjjh.getResultJson();
            return !spacePlanPrice.isEmpty() && spacePlanPrice.get("K005") != null && spacePlanPrice.getDoubleValue("K005") > 0.0D;
        }).collect(Collectors.groupingBy(MaintenanceOrder::getContract));
        if (contractListMap.isEmpty()) return;
        //外协派工集群空间类型生成供应商收入单和平台费用单
        OutboxPayloadWrapper wrapper = new OutboxPayloadWrapper();
        wrapper.setSubscriber("local.SupplierPlatformFnService.createIncomeAndExpense");
        Iterator<Map.Entry<Contract, List<MaintenanceOrder>>> iterator = contractListMap.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<Contract, List<MaintenanceOrder>> next = iterator.next();
            Map msg = MapUtil.mapper(
                    "contract", MapUtil.mapped(next.getKey()),
                    "maintenanceOrders", MapUtil.mapped(next.getValue())
            );
            wrapper.setPayload(JSON.toJSONString(msg));
            wrapper.setAggregateId(voucher.getId());
            SpringManager.getBean(OutboxEventService.class).sendSaveEvent(wrapper);
        }

    }

    private ServicePlan findSourceServicePlan(Voucher voucher) {
        String businessType = voucher.getOriginBusinessType();
        String source = voucher.getOrigin();
        if (source == null) return null;
        ServicePlan servicePlan = null;
        if (businessType.equals("RetailOrder")) {
            RetailOrder retailOrder = SpringManager.getBean(RetailOrderRepository.class).findOne(source);
            if (retailOrder.getSource() == null) return null;
            servicePlan = servicePlanRepository.findOne(retailOrder.getSource());
        }
        if (businessType.equals("ServicePlan")) {
            servicePlan = servicePlanRepository.findOne(source);
        }
        if (businessType.equals("SaleOrder")) {
            SaleOrder saleOrder = saleOrderRepository.findOne(voucher.getOrigin());
            if ("INNER_SALE".equals(saleOrder.getOrderType()))
                servicePlan = servicePlanRepository.findOne(saleOrder.getSource());
        }
        if ("InternalHelpReturnApproval".equals(businessType)) {
            SaleOrder saleOrder = saleOrderRepository.findOne(SpringManager.getBean(InternalHelpReturnApprovalRepository.class).findOne(voucher.getOrigin()).getOrigin());
            servicePlan = servicePlanRepository.findOne(saleOrder.getSource());
        }
        if (servicePlan == null) return null;
        return servicePlan;
    }

    private ServicePlan findSourceServicePlanBySaleOrder(Voucher voucher) {
        String businessType = voucher.getOriginBusinessType();
        String source = voucher.getOrigin();
        if (source == null) return null;
        ServicePlan servicePlan = null;
//        if (businessType.equals("RetailOrder")) {
//            RetailOrder retailOrder = SpringManager.getBean(RetailOrderRepository.class).findOne(source);
//            if (retailOrder.getSource() == null) return null;
//            servicePlan = servicePlanRepository.findOne(retailOrder.getSource());
//        }
//        if (businessType.equals("ServicePlan")) {
//            servicePlan = servicePlanRepository.findOne(source);
//        }
        if (businessType.equals("SaleOrder")) {
            SaleOrder saleOrder = saleOrderRepository.findOne(voucher.getOrigin());
            if ("INNER_SALE".equals(saleOrder.getOrderType()))
                servicePlan = servicePlanRepository.findOne(saleOrder.getSource());
        }
//        if("InternalHelpReturnApproval".equals(businessType)){
//            SaleOrder saleOrder = saleOrderRepository.findOne(SpringManager.getBean(InternalHelpReturnApprovalRepository.class).findOne(voucher.getOrigin()).getOrigin());
//            servicePlan = servicePlanRepository.findOne(saleOrder.getSource());
//        }
//        if (servicePlan==null) return null;
        return servicePlan;
    }
}
